
#include "StdAfx.h"
#include "DBTypeTable.h"
#include <StringObj.h>
#include <Tokenizer.h>

#include <sql.h>
#include <sqlext.h>

#ifdef WIN32
#include <srv.h>

#ifndef SRVINT8
#define SRVINT8	SRVINTN
#endif

#endif

DBTypeTable::DBTypeTable(){
	initialize_odbc();
	initialize_odbc_c();

#ifdef WIN32
	initialize_ods();
#endif

	initialize_oracle();
	initialize_size();
	initialize_SQLServer_typeName();
	initialize_oracle_typeName();
}

DBTypeTable::~DBTypeTable(){
	ODBC_.removeAll();
	ODBC_C_.removeAll();	

#ifdef WIN32
	ODS_.removeAll();
#endif

	ORACLE_.removeAll();
	size_.removeAll();	

	sql_server_type_name_.removeAll();
	sql_server_odbc_type_name_.removeAll();
	sql_server_odbc_c_type_name_.removeAll();

	oracle_type_name_.removeAll();
}

int DBTypeTable::getDBMS_ODBC_Type( char* name ){
	StringObj sql_server;
	sql_server = "Microsoft SQL Server";
	StringObj my_sql;
	my_sql = "MySQL";
	StringObj oracle;
	oracle = "Oracle";

	if( sql_server.isEqualIgnLetterType( name ) )
		return DEF_SQL_SERVER;

	if( my_sql.isEqualIgnLetterType( name ) )
		return DEF_MY_SQL;

	if( oracle.isEqualIgnLetterType( name ) )
		return DEF_ORACLE;

	return -1;
}

int DBTypeTable::getDBMS_Type( char* name ){
	StringObj sql_server;
	sql_server = "Microsoft SQL Server";
	StringObj my_sql;
	my_sql = "MySQL";
	StringObj oracle;
	oracle = "Oracle";
	StringObj postgres;
	postgres = "postgres";

	StringObj db;
	db = name;
	db.toLower();

	Tokenizer tok;
	if( tok.isTokenPresence( sql_server.toCharacters(), db.toCharacters() ) )
		return DEF_SQL_SERVER;

	if( tok.isTokenPresence( my_sql.toCharacters(), db.toCharacters() ) )
		return DEF_MY_SQL;

	if( tok.isTokenPresence( oracle.toCharacters(), db.toCharacters() ) )
		return DEF_ORACLE;

	return -1;
}

int DBTypeTable::getODBC_to_Type( int type ){
	int ret_type = DEF_TYPE_ERR;
	
	if(! ODBC_.get( type, ret_type ) )
		return DEF_TYPE_ERR;

	return ret_type;
}

int DBTypeTable::getODBC_to_ODBC_C( int type ){
	int def_type = getODBC_to_Type( type );
	if( def_type == DEF_TYPE_ERR )
		return DEF_TYPE_ERR;

	int odbc_c = getType_to_ODBC_C( def_type );
	if( odbc_c == DEF_TYPE_ERR )
		return DEF_TYPE_ERR;

	return odbc_c;
}

#ifdef WIN32
int DBTypeTable::getODBC_to_ODS( int type ){
	int def_type = getODBC_to_Type( type );

	if( def_type == DEF_TYPE_ERR )
		return DEF_TYPE_ERR;
	
	int ods = getType_to_ODS( def_type );
	if( ods == DEF_TYPE_ERR )
		return DEF_TYPE_ERR;

	return ods;
}
#endif

int DBTypeTable::getType_to_ODBC( int type ){
	int odbc = 0;

	if(! type_ODBC_.get( type, odbc ) )
		return DEF_TYPE_ERR;	

	return odbc;
}

int DBTypeTable::getType_to_ODBC_C( int type ){
	int odbc_c = 0;	

	if(! type_ODBC_C_.get( type, odbc_c ) )
		return DEF_TYPE_ERR;

	return odbc_c;
}

#ifdef WIN32
int DBTypeTable::getType_to_ODS( int type ){
	int ods = 0;

	if(! type_ODS_.get( type, ods ) )
		return DEF_TYPE_ERR;

	return ods;
}
#endif
	
int DBTypeTable::getODBC_C_to_ODBC( int type ){
	int def_type = getODBC_C_to_Type( type );
	if( def_type < 0 )
		return -1;

	int odbc = getType_to_ODBC( def_type );
	if( odbc == DEF_TYPE_ERR )
		return DEF_TYPE_ERR;
	
	return odbc;
}

int DBTypeTable::getODBC_C_to_Type( int type ){
	int def_type = 0;

	if(! ODBC_C_.get( type, def_type ) )
		return DEF_TYPE_ERR;

	return def_type;
}

#ifdef WIN32
int DBTypeTable::getODBC_C_to_ODS( int type ){
	int def_type = getODBC_C_to_Type( type );
	if( def_type < 0 )
		return -1;

	int ods = getType_to_ODS( def_type );
	if( ods == DEF_TYPE_ERR )
		return DEF_TYPE_ERR;

	return ods;
}


int DBTypeTable::getODS_to_Type( int type ){
	int def_type = 0;

	if(! ODS_.get( type, def_type ) )
		return DEF_TYPE_ERR;

	return def_type;
}

int DBTypeTable::getODS_to_ODBC( int type ){
	int def_type = getODS_to_Type( type );
	if( def_type == DEF_TYPE_ERR )
		return DEF_TYPE_ERR;

	int odbc = getType_to_ODBC( def_type );
	if( odbc == DEF_TYPE_ERR )
		return DEF_TYPE_ERR;

	return odbc;
}

int DBTypeTable::getODS_to_ODBC_C( int type ){
	int def_type = getODS_to_Type( type );
	if( def_type == DEF_TYPE_ERR )
		return DEF_TYPE_ERR;

	int odbc_c = getType_to_ODBC_C( def_type );
	if( odbc_c == DEF_TYPE_ERR )
		return DEF_TYPE_ERR;

	return odbc_c;
}

void DBTypeTable::initialize_ods(){
	ODS_.add( SRVINT4, DEF_TYPE_4INT );	
	ODS_.add( SRVFLT8, DEF_TYPE_8FLOAT );
	ODS_.add( SRVFLT4, DEF_TYPE_4FLOAT );
	ODS_.add( SRVINT8, DEF_TYPE_8INT );
	ODS_.add( SRVINT1, DEF_TYPE_1INT );
	ODS_.add( SRVINT2, DEF_TYPE_2INT );	
	ODS_.add( SRVBIGVARCHAR, DEF_TYPE_CHAR );
	ODS_.add( SRVVARBINARY, DEF_TYPE_BINARY );
	ODS_.add( SRVBIGBINARY, DEF_TYPE_BINARY );	
	ODS_.add( SRVBIT, DEF_TYPE_BIT );
	ODS_.add( SRVINTN, DEF_TYPE_4INT );
	ODS_.add( SRVFLTN, DEF_TYPE_4FLOAT );
	ODS_.add( SRVNUMERICN, DEF_TYPE_8INT );

	type_ODS_.add( DEF_TYPE_4INT, SRVINT4 );	
	type_ODS_.add( DEF_TYPE_8FLOAT, SRVFLT8 );
	type_ODS_.add( DEF_TYPE_4FLOAT, SRVFLT4 );
	type_ODS_.add( DEF_TYPE_8INT, SRVINT8 );
	type_ODS_.add( DEF_TYPE_1INT, SRVINT1 );
	type_ODS_.add( DEF_TYPE_2INT, SRVINT2 );	
	type_ODS_.add( DEF_TYPE_CHAR, SRVBIGVARCHAR );
	type_ODS_.add( DEF_TYPE_UCHAR, SRVBIGVARCHAR );
	type_ODS_.add( DEF_TYPE_U8INT, SRVINT8 );
	type_ODS_.add( DEF_TYPE_U1INT, SRVINT1 );
	type_ODS_.add( DEF_TYPE_U2INT, SRVINT2 );
	type_ODS_.add( DEF_TYPE_U4INT, SRVINT4 );
	type_ODS_.add( DEF_TYPE_BIT, SRVBIT );
	type_ODS_.add( DEF_TYPE_BINARY, SRVBIGBINARY );		
}
#endif

void DBTypeTable::initialize_odbc(){	
	ODBC_.add( SQL_INTEGER, DEF_TYPE_4INT );
	ODBC_.add( SQL_CHAR, DEF_TYPE_CHAR );
	ODBC_.add( SQL_DOUBLE, DEF_TYPE_8FLOAT );
	ODBC_.add( SQL_REAL, DEF_TYPE_4FLOAT );
	ODBC_.add( SQL_FLOAT, DEF_TYPE_8FLOAT );
	ODBC_.add( SQL_BIGINT, DEF_TYPE_8INT );
	ODBC_.add( SQL_TINYINT, DEF_TYPE_1INT );	
	ODBC_.add( SQL_SMALLINT, DEF_TYPE_2INT );	
	ODBC_.add( SQL_DATETIME, DEF_TYPE_CHAR );
	ODBC_.add( SQL_NUMERIC, DEF_TYPE_CHAR );	
	ODBC_.add( SQL_DECIMAL, DEF_TYPE_CHAR );
	ODBC_.add( SQL_BINARY, DEF_TYPE_BINARY );
	ODBC_.add( SQL_BIT, DEF_TYPE_BIT );
	ODBC_.add( SQL_BIGINT, DEF_TYPE_8INT );
	ODBC_.add( SQL_TIME, DEF_TYPE_CHAR );
	ODBC_.add( SQL_TIMESTAMP, DEF_TYPE_CHAR );

	type_ODBC_.add( DEF_TYPE_4INT, SQL_INTEGER );
	type_ODBC_.add( DEF_TYPE_CHAR, SQL_CHAR );
	type_ODBC_.add( DEF_TYPE_UCHAR, SQL_CHAR );
	type_ODBC_.add( DEF_TYPE_8FLOAT, SQL_DOUBLE );
	type_ODBC_.add( DEF_TYPE_4FLOAT, SQL_REAL );
	type_ODBC_.add( DEF_TYPE_8INT, SQL_BIGINT );
	type_ODBC_.add( DEF_TYPE_1INT, SQL_TINYINT );	
	type_ODBC_.add( DEF_TYPE_2INT, SQL_SMALLINT );	
	type_ODBC_.add( DEF_TYPE_BINARY, SQL_BINARY );
	type_ODBC_.add( DEF_TYPE_U8INT, SQL_BIGINT );
	type_ODBC_.add( DEF_TYPE_U1INT, SQL_TINYINT );	
	type_ODBC_.add( DEF_TYPE_U2INT, SQL_SMALLINT );
	type_ODBC_.add( DEF_TYPE_U4INT, SQL_INTEGER );
	type_ODBC_.add( DEF_TYPE_BIT, SQL_BIT );
}

void DBTypeTable::initialize_odbc_c(){	
	ODBC_C_.add( SQL_C_SBIGINT, DEF_TYPE_8INT );	
	ODBC_C_.add( SQL_C_UBIGINT, DEF_TYPE_U8INT );
	ODBC_C_.add( SQL_C_TINYINT, DEF_TYPE_1INT );
	ODBC_C_.add( SQL_C_STINYINT, DEF_TYPE_1INT );
	ODBC_C_.add( SQL_C_UTINYINT, DEF_TYPE_U1INT );
	ODBC_C_.add( SQL_C_CHAR, DEF_TYPE_CHAR );	
	ODBC_C_.add( SQL_C_LONG, DEF_TYPE_4INT );
	ODBC_C_.add( SQL_C_SLONG, DEF_TYPE_4INT );
	ODBC_C_.add( SQL_C_ULONG, DEF_TYPE_U4INT );
	ODBC_C_.add( SQL_C_SHORT, DEF_TYPE_2INT );
	ODBC_C_.add( SQL_C_SSHORT, DEF_TYPE_2INT );
	ODBC_C_.add( SQL_C_USHORT, DEF_TYPE_U2INT );
	ODBC_C_.add( SQL_C_DOUBLE, DEF_TYPE_8FLOAT );
	ODBC_C_.add( SQL_C_FLOAT, DEF_TYPE_4FLOAT );		
	ODBC_C_.add( SQL_C_BINARY, DEF_TYPE_BINARY );
	ODBC_C_.add( SQL_C_BIT, DEF_TYPE_BIT );

	type_ODBC_C_.add( DEF_TYPE_8INT, SQL_C_SBIGINT );	
	type_ODBC_C_.add( DEF_TYPE_U8INT, SQL_C_UBIGINT );
	type_ODBC_C_.add( DEF_TYPE_1INT, SQL_C_TINYINT );	
	type_ODBC_C_.add( DEF_TYPE_U1INT, SQL_C_UTINYINT );
	type_ODBC_C_.add( DEF_TYPE_CHAR, SQL_C_CHAR );
	type_ODBC_C_.add( DEF_TYPE_UCHAR, SQL_C_CHAR );	
	type_ODBC_C_.add( DEF_TYPE_4INT, SQL_C_LONG );	
	type_ODBC_C_.add( DEF_TYPE_U4INT, SQL_C_ULONG );
	type_ODBC_C_.add( DEF_TYPE_2INT, SQL_C_SHORT );	
	type_ODBC_C_.add( DEF_TYPE_U2INT, SQL_C_USHORT );
	type_ODBC_C_.add( DEF_TYPE_8FLOAT, SQL_C_DOUBLE );
	type_ODBC_C_.add( DEF_TYPE_4FLOAT, SQL_C_FLOAT );		
	type_ODBC_C_.add( DEF_TYPE_BINARY, SQL_C_BINARY );
	type_ODBC_C_.add( DEF_TYPE_BIT, SQL_C_BIT );
}

void DBTypeTable::initialize_oracle(){
}

void DBTypeTable::initialize_size(){
	size_.add( DEF_TYPE_NONE, 0 );
	size_.add( DEF_TYPE_CHAR, 0 );
	size_.add( DEF_TYPE_UCHAR, 0 );
	size_.add( DEF_TYPE_1INT, 1 );
	size_.add( DEF_TYPE_2INT, 2 );
	size_.add( DEF_TYPE_4INT, 4 );
	size_.add( DEF_TYPE_8INT, 8 );
	size_.add( DEF_TYPE_U1INT, 1 );
	size_.add( DEF_TYPE_U2INT, 2 );	
	size_.add( DEF_TYPE_U4INT, 4 );	
	size_.add( DEF_TYPE_U8INT, 8 );	
	size_.add( DEF_TYPE_4FLOAT, 4 );	
	size_.add( DEF_TYPE_8FLOAT, 8 );
	size_.add( DEF_TYPE_BIT, 1 );
	size_.add( DEF_TYPE_BINARY, 0 );
}

void DBTypeTable::initialize_SQLServer_typeName(){		
	sql_server_type_name_.add( DEF_TYPE_CHAR, "CHAR" );
	sql_server_type_name_.add( DEF_TYPE_UCHAR, "CHAR" );
	sql_server_type_name_.add( DEF_TYPE_1INT, "TINYINT" );
	sql_server_type_name_.add( DEF_TYPE_2INT, "SMALLINT" );
	sql_server_type_name_.add( DEF_TYPE_4INT, "INT" );
	sql_server_type_name_.add( DEF_TYPE_8INT, "BIGINT" );
	sql_server_type_name_.add( DEF_TYPE_U1INT, "TINYINT" );
	sql_server_type_name_.add( DEF_TYPE_U2INT, "SMALLINT" );
	sql_server_type_name_.add( DEF_TYPE_U4INT, "INT" );
	sql_server_type_name_.add( DEF_TYPE_U8INT, "BIGINT" );
	sql_server_type_name_.add( DEF_TYPE_4FLOAT, "FLOAT" );	
	sql_server_type_name_.add( DEF_TYPE_8FLOAT, "FLOAT" );
	sql_server_type_name_.add( DEF_TYPE_BIT, "BIT" );
	sql_server_type_name_.add( DEF_TYPE_BINARY, "BINARY" );
	sql_server_type_name_.add( DEF_TYPE_DATETIME, "DATETIME" );	
	
	sql_server_odbc_type_name_.add( SQL_INTEGER, "INT" );
	sql_server_odbc_type_name_.add( SQL_CHAR, "CHAR" );
	sql_server_odbc_type_name_.add( SQL_DOUBLE, "FLOAT" );
	sql_server_odbc_type_name_.add( SQL_REAL, "REAL" );
	sql_server_odbc_type_name_.add( SQL_FLOAT, "FLOAT" );
	sql_server_odbc_type_name_.add( SQL_BIGINT, "BIGINT" );
	sql_server_odbc_type_name_.add( SQL_TINYINT, "TINYINT" );	
	sql_server_odbc_type_name_.add( SQL_SMALLINT, "SMALLINT" );	
	sql_server_odbc_type_name_.add( SQL_DATETIME, "DATETIME" );
	sql_server_odbc_type_name_.add( SQL_NUMERIC, "NUMERIC" );	
	sql_server_odbc_type_name_.add( SQL_DECIMAL, "DECIMAL" );
	sql_server_odbc_type_name_.add( SQL_BINARY, "BINARY" );
	sql_server_odbc_type_name_.add( SQL_BIT, "BIT" );
	sql_server_odbc_type_name_.add( SQL_BIGINT, "BIGINT" );
	sql_server_odbc_type_name_.add( SQL_TIME, "DATETIME" );
	sql_server_odbc_type_name_.add( SQL_TIMESTAMP, "DATETIME" );
	sql_server_odbc_type_name_.add( SQL_TYPE_TIMESTAMP, "DATETIME" );	
	sql_server_odbc_type_name_.add( SQL_TYPE_DATE, "DATETIME" );	
	sql_server_odbc_type_name_.add( SQL_TYPE_TIME, "DATETIME" );		
	
	sql_server_odbc_c_type_name_.add( SQL_C_SBIGINT, "BIGINT" );	
	sql_server_odbc_c_type_name_.add( SQL_C_UBIGINT, "BIGINT" );
	sql_server_odbc_c_type_name_.add( SQL_C_TINYINT, "TINYINT" );
	sql_server_odbc_c_type_name_.add( SQL_C_STINYINT, "TINYINT" );
	sql_server_odbc_c_type_name_.add( SQL_C_UTINYINT, "TINYINT" );
	sql_server_odbc_c_type_name_.add( SQL_C_CHAR, "CHAR" );	
	sql_server_odbc_c_type_name_.add( SQL_C_LONG, "INT" );
	sql_server_odbc_c_type_name_.add( SQL_C_SLONG, "INT" );
	sql_server_odbc_c_type_name_.add( SQL_C_ULONG, "INT" );
	sql_server_odbc_c_type_name_.add( SQL_C_SHORT, "SMALLINT" );
	sql_server_odbc_c_type_name_.add( SQL_C_SSHORT, "SMALLINT" );
	sql_server_odbc_c_type_name_.add( SQL_C_USHORT, "SMALLINT" );
	sql_server_odbc_c_type_name_.add( SQL_C_DOUBLE, "FLOAT" );
	sql_server_odbc_c_type_name_.add( SQL_C_FLOAT, "REAL" );		
	sql_server_odbc_c_type_name_.add( SQL_C_BINARY, "BINARY" );
	sql_server_odbc_c_type_name_.add( SQL_C_BIT, "BIT" );
	sql_server_odbc_c_type_name_.add( SQL_C_TYPE_DATE, "DATETIME" );
	sql_server_odbc_c_type_name_.add( SQL_C_TYPE_TIME, "DATETIME" );
	sql_server_odbc_c_type_name_.add( SQL_C_TYPE_TIMESTAMP, "DATETIME" );
}

void DBTypeTable::initialize_oracle_typeName(){
	oracle_type_name_.add( DEF_TYPE_CHAR, "VARCHAR2" );
	oracle_type_name_.add( DEF_TYPE_UCHAR, "VARCHAR2" );
	oracle_type_name_.add( DEF_TYPE_1INT, "NUMBER" );
	oracle_type_name_.add( DEF_TYPE_2INT, "NUMBER" );
	oracle_type_name_.add( DEF_TYPE_4INT, "NUMBER" );
	oracle_type_name_.add( DEF_TYPE_8INT, "NUMBER" );
	oracle_type_name_.add( DEF_TYPE_U1INT, "NUMBER" );
	oracle_type_name_.add( DEF_TYPE_U2INT, "NUMBER" );
	oracle_type_name_.add( DEF_TYPE_U4INT, "NUMBER" );
	oracle_type_name_.add( DEF_TYPE_U8INT, "NUMBER" );
	oracle_type_name_.add( DEF_TYPE_4FLOAT, "FLOAT" );	
	oracle_type_name_.add( DEF_TYPE_8FLOAT, "FLOAT" );
	oracle_type_name_.add( DEF_TYPE_BIT, "NUMBER" );
	oracle_type_name_.add( DEF_TYPE_BINARY, "BLOB" ); //?
	oracle_type_name_.add( DEF_TYPE_DATETIME, "DATE" ); //?	
}

int DBTypeTable::getTypeSize( int type ){
	if( type == DEF_TYPE_ERR )
		return -1;

	int size = 0;

	if(! size_.get( type, size ) )
		return -1;

	return size;
}

#ifdef WIN32
int DBTypeTable::getODSSize( int ods_type ){
	int default_type = getODS_to_Type( ods_type );
	return getTypeSize( default_type );
}
#endif

int DBTypeTable::getODBCSize( int odbc_type ){
	int default_type = getODBC_to_Type( odbc_type );
	return getTypeSize( default_type );
}

bool DBTypeTable::isString( int type ){
	if( type ==	DEF_TYPE_CHAR )
		return true;
	
	if( type == DEF_TYPE_UCHAR )
		return true;

	return false;
}

bool DBTypeTable::isODBCString( int odbc_type ){
	int default_type = getODBC_to_Type( odbc_type );
	return isString( default_type );
}

char* DBTypeTable::getSQLServer_Type( int type ){
	static std::string sqlServer_type;
	if(! sql_server_type_name_.get( type, sqlServer_type ) )
		return 0;

	return (char*)sqlServer_type.c_str();
}

char* DBTypeTable::getSQLServer_ODBC_Type( int odbc_type ){
	static std::string sqlServer_odbc_type;
	if(! sql_server_odbc_type_name_.get( odbc_type, sqlServer_odbc_type ) )
		return 0;

	return (char*)sqlServer_odbc_type.c_str();	
}

char* DBTypeTable::getSQLServer_ODBC_C_Type( int odbc_c_type ){
	static std::string sql_server_odbc_c;
	if(! sql_server_odbc_c_type_name_.get( odbc_c_type, sql_server_odbc_c ) )
		return 0;

	return (char*)sql_server_odbc_c.c_str();	
}

char* DBTypeTable::getOracle_Type( int type ){
	static std::string oracle_type;
	if(! oracle_type_name_.get( type, oracle_type ) )
		return 0;

	return (char*)oracle_type.c_str();
}

